package io.github.openfeign.spring.controller;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;

@Controller
@RequestMapping("/example")
@Slf4j
public class UploadController {

    @ResponseBody
    @GetMapping(value = "/test")
    public String test() {
        return "success";
    }

    @ResponseBody
    @PostMapping(value = "/uploads", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public UploadResult uploads(@RequestPart(value = "attachments", required = false) List<MultipartFile> attachments,
                                UploadParam uploadParam,
                                @RequestHeader("testHeader") String testHeader,
                                @RequestParam("testParam") String testParam) {
        final long fileSize = Optional.of(attachments)
                .map(Collection::stream)
                .orElseGet(Stream::empty)
                .mapToLong(this::getUploadFileSize)
                .sum();

        return UploadResult.builder()
                .uploadParam(uploadParam)
                .fileSize(fileSize)
                .testHeader(testHeader)
                .testParam(testParam)
                .build();
    }

    @ResponseBody
    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public UploadResult uploads(@RequestPart(value = "attachments", required = false) MultipartFile attachment,
                                UploadParam uploadParam,
                                @RequestHeader("testHeader") String testHeader,
                                @RequestParam("testParam") String testParam) {
        final long fileSize = getUploadFileSize(attachment);

        return UploadResult.builder()
                .uploadParam(uploadParam)
                .fileSize(fileSize)
                .testHeader(testHeader)
                .testParam(testParam)
                .build();
    }

    @SneakyThrows
    private long getUploadFileSize(final MultipartFile attachment) {
        log.info("OriginalFilename: {}", attachment.getOriginalFilename());
        log.info("ContentType: {}", attachment.getContentType());

        final byte[] buffer = new byte[4096]; // 4KB缓冲区
        long size = 0;
        try (final InputStream is = attachment.getInputStream()) {
            int bytesRead = is.read(buffer);
            while (bytesRead > 0) {
                size += bytesRead;
                bytesRead = is.read(buffer); // 丢弃
            }
        }
        return size;
    }
}
